/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package pessoas.collection;

import java.util.ArrayList;
import pessoas.model.Contato;
import pessoas.model.Operadora;
import pessoas.model.UFNonoDigito;
import pessoas.operadoras.CarregaOperadoras;
import pessoas.ufNonoDigito.EsNonoDigito;
import pessoas.ufNonoDigito.RjNonoDigito;
import pessoas.ufNonoDigito.SpNonoDigito;
import pessoas.ufNonoDigito.UFNonoDigitoProcessor;

/**
 *
 * @author Bush
 */
public class Operadoras {

    private ArrayList<Operadora> operadoras;
    private CarregaOperadoras carregarOperadoras;
    private static Operadoras instancia;
    private UFNonoDigitoProcessor ufProcessor;

    private Operadoras() throws Exception {
        operadoras = new ArrayList<Operadora>();
        carregarOperadoras = new CarregaOperadoras();
        addUfsNonoDigito();
        carregarOperadoras();
    }

    public static Operadoras getInstancia() throws Exception {
        if (instancia == null) {
            instancia = new Operadoras();
        }
        return instancia;
    }

    private void carregarOperadoras() throws Exception {
        this.operadoras = carregarOperadoras.inicializaOperadoras();
    }

    public ArrayList<Operadora> getOperadoras() {
        return operadoras;
    }

    public Contato detectaUfOperadora(Contato contato) throws Exception {
        if (dddExiste(contato.getTelefone().substring(1, 3))
                && prefixoExiste(contato.getTelefone().substring(1, 3), contato.getTelefone().substring(4, 6))) {  //Verificica se os numeros informados são válidos

            contato.setUf(retornaUf(contato.getTelefone().substring(1, 3)));
            contato.setOperadora(retornaOperadora(contato.getUf(), contato.getTelefone().substring(4, 6)));
            contato.setTelefone(verificaNonoDigito(contato.getTelefone()));  
            return contato;

        } else {
            throw new Exception("Informe um ddd e um número válido!!");
        }

    }

    public boolean dddExiste(String ddd) {

        for (int i = 0; i < operadoras.size(); i++) {
            String ddds[] = operadoras.get(i).getDdd().split(",");
            for (int j = 0; j < ddds.length; j++) {
                if (ddds[j].equals(ddd)) {
                    return true;
                }
            }
        }
        return false;
    }

    public boolean prefixoExiste(String uf, String prefixo) {

        for (int i = 0; i < operadoras.size(); i++) {
            String pref[] = operadoras.get(i).getPrefixo().split(",");
            String ddds[] = operadoras.get(i).getDdd().split(",");
            for (int j = 0; j < ddds.length; j++) {
                for (int k = 0; k < pref.length; k++) {
                    if (ddds[j].equals(uf) && pref[k].equals(prefixo)) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    public String retornaUf(String ddd) {

        for (int i = 0; i < operadoras.size(); i++) {
            String ddds[] = operadoras.get(i).getDdd().split(",");
            for (int j = 0; j < ddds.length; j++) {
                if (ddds[j].equals(ddd)) {
                    return operadoras.get(i).getUf();
                }
            }
        }
        return "";
    }

    private String retornaOperadora(String uf, String prefixo) {

        for (int i = 0; i < operadoras.size(); i++) {
            String pref[] = operadoras.get(i).getPrefixo().split(",");
            for (int j = 0; j < pref.length; j++) {
                if (operadoras.get(i).getUf().equals(uf) && pref[j].equals(prefixo)) {
                    return operadoras.get(i).getOperadora();
                }
            }
        }
        return "";
    }

    private String verificaNonoDigito(String telefone) throws Exception {   //Método cliente do Padrão Chain of responsibility, usado para detecção de Nono Dígito
        String ddd = telefone.substring(1, 3);
        String tel = telefone.substring(4, 8) + telefone.substring(9);
        UFNonoDigito ufNono = new UFNonoDigito();
        ufNono.add(ddd);

        if (this.ufProcessor.handleRequest(ufNono)) {
            if (tel.length() == 8) {
                String telAlterado = telefone.substring(0, 4) + "9" + telefone.substring(4);
                return telAlterado;
            }
        } else if (tel.length() == 9) {
            String telAlterado = telefone.substring(0, 4) + telefone.substring(5);
            return telAlterado;
        }

        return telefone;
    }

    private void addUfsNonoDigito() {
        UFNonoDigitoProcessor uFProcessor = new UFNonoDigitoProcessor();
        uFProcessor.addEmailHandler(new EsNonoDigito());
        uFProcessor.addEmailHandler(new RjNonoDigito());
        uFProcessor.addEmailHandler(new SpNonoDigito());
        this.ufProcessor = uFProcessor;
    }

}
